
import sys
import time
from collections import OrderedDict
from PyMimircache import Cachecow
from PyMimircache.cache.lru import LRU
from PyMimircache.cacheReader.requestItem import Req
"""
用于过滤在这一层cache未命中，需要访问下一层cache的数据
针对不同的trace，需要改动的是trace_path和miss_path；
针对不同层次的cache，需要改动的是cache_size和speed
"""
c=Cachecow()

#运行此脚本时格式为 'python 脚本名 存储层次 trace路径'
#定义trace路径,获取reader
# trace_path="traces/2_pools.txt"
trace_path=sys.argv[2]
reader=c.open(trace_path)

# 假设DRAM大小为4G，则cache_size最大为4G/1T*HDD_cache_size,延迟为100ns
if sys.argv[1]=='DRAM':
    layer_cache_size=int(0.004*reader.get_num_of_uniq_req())
    if layer_cache_size<1:
        layer_cache_size=1
    speed=1
    miss_path="traces/DRAM_miss.txt"
# 假设SSD大小为500G，则cache_size最大为(500G/1T)*HDD_cache_size，延迟为150us，速度为150*1000/100
elif sys.argv[1]=='SSD':
    layer_cache_size=int(0.5*reader.get_num_of_uniq_req())
    speed=1500
    miss_path="traces/SSD_miss.txt"
# 假设HDD大小为1T，则HDD的大小应能存完所有trace，即len（trace），延迟为10ms，速度为10*1000*1000/100   
elif sys.argv[1]=='HDD':
    layer_cache_size=reader.get_num_of_uniq_req()
    speed=100000


#定义LRUcache的大小,lru_cache中按插入顺序排列
lru_cache=LRU(cache_size=layer_cache_size)
cache_size=lru_cache.cache_size
print("cache is ",cache_size)
print("speed is ",speed)

#获取trace中的请求数目
n_req=reader.get_num_of_req()
print("1. n_req is ",n_req)

"""
依次读trace中的每一行req：
access————
1. 判断这个req是否在lru_cache中
2. 若在，则跳过（access）
3. 若不在，,插入当前req（insert），再判断lru_cache中的数目
    3.1 数目<cache_size
    3.2 数目>=cache_size，将cache中的某个项换出（evict）
4. 将当前req记录下来作为cache_miss数据
"""
#定义cache miss文件
# miss_path="traces/2_pools_miss1.txt"
miss_file = open(miss_path, mode='a+')

#将reader中的数据依次读出来，转换为request对象 
# n_req=3
evict_item_list = [] # 保存evict对象
for n in range(n_req): 
    request=reader.read_one_req()
    req=Req(request)
    print("req's id is",req.item_id)

    #print("1111",lru_cache)
    # 根据存储层次的延迟决定执行时间的比
    for i in range(speed*100):
        continue

    if lru_cache.access(req,evict_item_list=evict_item_list):
        continue
    # print("222",lru_cache)
    miss_file.write(req.item_id)
    miss_file.write('\n')

# print(evict_item_list)

miss_file.close

print(lru_cache)
